// strictly LRU

var HeaderCache = {};

HeaderCache.cache = null;
HeaderCache.cachesize = 0;
HeaderCache.recency = null;
HeaderCache.maxsize = 25;

HeaderCache.init = function() {
    AppalachianDebug.trace("header-cache.js", "> init");
    HeaderCache.cache = new Object();
    HeaderCache.recency = new Object();
    HeaderCache.observer.register();
    // @@@ use pref setting for maxsize if any exists
    AppalachianDebug.trace("header-cache.js", "< init");
};

HeaderCache.put = function(url, headers) {
    AppalachianDebug.trace("header-cache.js", "> put " + url);
    if (HeaderCache.cachesize > HeaderCache.maxsize) {
        HeaderCache.evict(HeaderCache.cachesize - HeaderCache.maxsize);
    }
    HeaderCache.cachesize++;
    HeaderCache.cache[url] = headers;
    var d = new Date().getTime();
    HeaderCache.recency[d] = url;
    AppalachianDebug.trace("header-cache.js", "< put");
};

HeaderCache.get = function(callback, url) {
    AppalachianDebug.trace("header-cache.js", "> get " + url);
    if (HeaderCache.cache[url]) {
        AppalachianDebug.trace("header-cache.js", "get hit");
        AppalachianDebug.trace("header-cache.js", "< get");
        callback(HeaderCache.cache[url]);
    } else {
        // cache miss, go out and grab that url
        AppalachianDebug.trace("header-cache.js", "get miss, fetching");
        var httplib = new YadisHTTP(url);
        var error = function() {
            callback(null);
        };
        var success = function() {
            callback(HeaderCache.cache);
        };
        httplib.doGET(success, error, false, true);
        AppalachianDebug.trace("header-cache.js", "< get");
    }
};

HeaderCache.evict = function(count) {
    AppalachianDebug.trace("header-cache.js", "> evict " + count);
    for (var i = 0; i < count; i++) {
        var minUrl = null;
        var min = 0;
        for (var j in HeaderCache.recency) {
            if (j < min || min == 0) {
                minUrl = HeaderCache.recency[j];
                min = j;
            }
        }
        AppalachianDebug.trace("header-cache.js", "evict: " + min + " " + minUrl);
        delete HeaderCache.cache[minUrl];
        delete HeaderCache.recency[min];
        HeaderCache.cachesize--;
    }
    AppalachianDebug.trace("header-cache.js", "< evict");
};

HeaderCache.destroy = function() {
    AppalachianDebug.trace("header-cache.js", "> destroy");
    HeaderCache.cache = null;
    HeaderCache.recency = null;
    HeaderCache.observer.unregister();
    AppalachianDebug.trace("header-cache.js", "< destroy");
};

HeaderCache.observer = {
    observe : function(subject, topic, data) {
        AppalachianDebug.trace('header-cache.js','> observe ' + topic);
        if (subject != null) {
            var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
            AppalachianDebug.trace('header-cache.js', httpChannel.URI.asciiSpec);
            var headers = new Object();
            headers.location = null;
            headers.isXRDS = false;
            if (topic == "http-on-examine-response") {
                try {
                    type = httpChannel.getResponseHeader(HTTP_CONTENT_TYPE).toLowerCase();
                    if (type.search(/html/i) >= 0 || type == '*/*') {
                        try {
                            headers.location = httpChannel.getResponseHeader(YADIS_HTTP_HEADER);
                        } catch(e) { }
                    }
                    try {
                        headers.isXRDS = (type.indexOf(YADIS_MIME_TYPE) >= 0 || type.indexOf(XML_TEXT_MIME_TYPE) >= 0 || type.indexOf(XML_APP_MIME_TYPE) >= 0);
                    } catch(e) { }
                    HeaderCache.put(httpChannel.URI.asciiSpec, headers);
                } catch (err) { }
            }
        }
        AppalachianDebug.trace('header-cache.js','< observe');
    },

    register : function() {
        var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
        observerService.addObserver(this, "http-on-examine-response", false);
    },

    unregister : function() {
        var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
        observerService.removeObserver(this, "http-on-examine-response");
    },

    QueryInterface : function(aIID) {
        if (aIID.equals(Components.interfaces.nsISupports) ||
            aIID.equals(Components.interfaces.nsIObserver))
        return this;
        throw Components.results.NS_NOINTERFACE;
    }
};
